iT邦幫忙

2024 iThome 鐵人賽

DAY 13
0
生成式 AI

Semantic Kernel 的魔力-用.NET探索生成式應用系列 第 13

生成式AI的多樣應用:從文字到圖像 II - 使用Plugin

  • 分享至 

  • xImage
  •  

前一篇文章示範使用 Semantic Kernel 內建的模型連接服務串接 OpenAI 的 DALL-E 模型,快速做成一個以文生圖的應用,然而有些時候這些內建的服務無法滿足需求時,又該怎麼辦?
以前一篇的範例為例,內建的服務所提供的參數有限,它並沒有提供 quality(成像品質)、style(成像風格)、n(成像數量) 等這些DALL-E 模型 API 參數。這時候我們就可以利用 Plugins 自已實現 API 呼叫來取代原本內建的模型連接服務。

使用 Plugin 建立自訂 API 呼叫

  • 建立 kernel 物件
    這一次不掛 AddOpenAITextToImage,但依然要掛 AddOpenAIChatCompletion 服務,因為我們還是需要用本文對話驅動以文生圖
var kernel = Kernel.CreateBuilder()
            .AddOpenAIChatCompletion(modelId: Config.openai_modelId, apiKey: Config.openai_apiKey)
            .Build();
  • 撰寫 Plugins
    建立 GenImage 方法,直接呼叫 OpenAI REST API ,requestBody依需求配置所需要的參數,例如:quality(成像品質)、style(成像風格)、n(成像數量) 等。在 GenImage 方法以及方法參數 string prompt 上增加 KernelFunction 與 Description 描述,如果有看本系列前面關於 Plugins 教學文章的話,應該會知道這是個關鍵,Description 的文字描述品質是 Semantic Kernel 框架裡讓 LLMs 能實現在需要時自動呼叫 Plugin Function 的關鍵。
public class OpenAIPlugin
{
    private static readonly HttpClient client = new HttpClient();

    [KernelFunction, Description("Given a prompt will generate a new image.")]
    public string GenImage([Description("user prompt for generate image")] string prompt)
    {
        var apiKey = Config.openai_apiKey; // 請替換為您的 API 金鑰
        var requestBody = new
        {
            model = "dall-e-3",
            prompt = prompt,
            n = 1,            //number of images to generate,dall-e-3, only n=1 is supported
            quality = "hd",  //standard or hd
            style = "vivid", //vivid or natural
            size = "1024x1024"
        };

        var content = new StringContent(
            JsonConvert.SerializeObject(requestBody),
            Encoding.UTF8, "application/json"
        );

        client.DefaultRequestHeaders.Clear();
        client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");

        var response = client.PostAsync("https://api.openai.com/v1/images/generations", content).GetAwaiter().GetResult();
        response.EnsureSuccessStatusCode();

        var responseBody = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
        var jsonResponse = JObject.Parse(responseBody);
        var imageUrl = jsonResponse["data"][0]["url"].ToString();

        return imageUrl;
    }
}
  • kernel 掛載 Plugin
    將撰寫好的 Plugin 附掛到 kernel 物件上,並且建立 settings 物件配置自動呼叫 Plugin Function。
kernel.Plugins.AddFromType<OpenAIPlugin>();

OpenAIPromptExecutionSettings settings = new() { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions };
  • prompt 撰寫與呼叫
    這時候 prompt 怎麼寫就很重要的,因為要自動驅動 Plugin Function的呼叫,也就表示必須讓 Semantic Kernel+LLMs 足以認知到現在使用者的這個生成需求必須有 Plugin Function 的幫忙才能完成,因此關鍵就在 prompt 了。
  1. 如果 prompt 這樣寫
    執行後會發現並沒有產生圖片,反而是直接聊天對話起來了,原因就在於這個 prompt 裡沒有任何的語意足自動驅動 Plugin Function 的呼叫。
var imageDescription ="一鄉二里共三夫子,不識四書五經六義,竟敢教七八九子,十分大膽";
Console.WriteLine("Image URL: " + await kernel.InvokePromptAsync(imageDescription, new(settings)));

https://ithelp.ithome.com.tw/upload/images/20240926/20126569YAlMFd5UbZ.png

  1. 如果 prompt 這樣寫就對了
    這個 prompt 裡明確要求產生圖片,並且要求回覆圖片的網址,不要有其它任何的解釋。因此語意上是足夠表達需要以文生圖,因此必須要驅動 Plugin Function 的呼叫。而能夠明確知道要呼叫哪一個 Plugin Function 則取決於在設計 Plugin Function 時的 Description 有沒有寫好。
var imageDescription =
"""
請根據以下描述,產生圖片,你只需回覆圖片的網址,不要有其它任何的解釋。

### 描述
一鄉二里共三夫子,不識四書五經六義,竟敢教七八九子,十分大膽
""";
Console.WriteLine("Image URL: " + await kernel.InvokePromptAsync(imageDescription, new(settings)));

https://ithelp.ithome.com.tw/upload/images/20240926/20126569S7BsOXNfEh.png

結語

當 Semantic Kernel 裡所提供的內建服務或 Plugin 無法滿足需求時,做為一個高度抽象化的 Semantic Kernel 是有足夠的方式可以支援客製化處理的。以本次的情境來說,透過撰寫 Plugin 就能有效的解決。也許讀者會產生另一個疑問那一開始就直接呼叫 OpenAI REST API ,何必用 Semantic Kernel 再寫 Plugin 呢 ? 其實在本系列第一篇就採討了這個問題,在簡單的LLMs應用當然 REST API 就能實現,但如果想進一步使用包含對話記錄、RAG 等,這時候有個框架可以套用會相對方便很多,更細的內容可以參考本系列第一篇文章。


上一篇
生成式AI的多樣應用:從文字到圖像
下一篇
生成式AI的多樣應用:文本與語音
系列文
Semantic Kernel 的魔力-用.NET探索生成式應用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言